﻿
using System.Windows.Input;
using ASPItalia.ModelVirtualCasting.WPF.ViewModels.Command;
using ASPItalia.ModelVirtualCasting.WPF.Common.Messaging;
using ASPItalia.ModelVirtualCasting.WPF.Common;
using System.ComponentModel;
using System.Windows.Data;
using System;
using System.Linq;
using ASPItalia.ModelVirtualCasting.WPF.Models;
namespace ASPItalia.ModelVirtualCasting.WPF.ViewModels
{

    public class MainViewModel : AsyncViewModel
    {

        private NewCandidatesViewModel newCandidatesViewModel;

        private ObservableCollectionEx<ModelViewModel> _candidates;
        private ObservableCollectionEx<ModelViewModel> _models;

        private String _modelSearch;
        private String _candiateSearch;

        private ModelViewModel _currentModel;

        public MainViewModel()
        {
            this.OpenCurrentMultimediaCommand = new RelayCommand(OpenCurrentMultimedia, CanOpenCurrentMultimedia);
            this.RecordMovieCommand = new RelayCommand(RecordMovie, CanRecordMovie);
        }

        #region Properties

        public ModelViewModel CurrentModel
        {
            get { return _currentModel; }
            set
            {
                ModelViewModel old = _currentModel;
                _currentModel = value;
                OnPropertyChanged("CurrentModel");
                this.Messenger.Send(new PropertyChangedMessage<ModelViewModel>(old, value, "CurrentModel"));
            }
        }

        /// <summary>
        /// Text to apply to filter models list
        /// </summary>
        public String ModelSearch
        {
            get { return _modelSearch; }
            set
            {
                _modelSearch = value;
                if (value != null)
                    this.ModelsView.Filter = GetFilterForModel(value);
                else
                    this.ModelsView.Filter = null;

                OnPropertyChanged("ModelSearch");
            }
        }

        /// <summary>
        /// Text to apply to filter candidates list
        /// </summary>
        public String CandidateSearch
        {
            get { return _candiateSearch; }
            set
            {
                _candiateSearch = value;
                if (value != null)
                    this.CandidatesView.Filter = GetFilterForModel(value);
                else
                    this.CandidatesView.Filter = null;

                OnPropertyChanged("CandidateSearch");
            }
        }

        public ObservableCollectionEx<ModelViewModel> Candidates
        {
            get
            {
                if (_candidates == null)
                    _candidates = new ObservableCollectionEx<ModelViewModel>();
                return _candidates;
            }
        }

        public ObservableCollectionEx<ModelViewModel> Models
        {
            get
            {
                if (_models == null)
                    _models = new ObservableCollectionEx<ModelViewModel>();
                return _models;
            }
        }

        public ICollectionView ModelsView
        {
            get { return CollectionViewSource.GetDefaultView(this.Models); }
        }

        public ICollectionView CandidatesView
        {
            get { return CollectionViewSource.GetDefaultView(this.Candidates); }
        }

        public string Title
        {
            get { return "Model Virtual Casting Manager"; }
        }

        #endregion

        #region Commands

        public ICommand CloseCommand
        {
            get;
            private set;
        }

        public ICommand RecordMovieCommand
        {
            get;
            private set;
        }

        public ICommand OpenCurrentMultimediaCommand
        {
            get;
            private set;
        }

        #endregion

        public void SelectStartupCandidate()
        {
            newCandidatesViewModel = new NewCandidatesViewModel();

            ShowDialogMessage dialogMessage = new ShowDialogMessage(newCandidatesViewModel, SelectStartupCandidateCallback);
            this.Messenger.Send(dialogMessage);

            this.ExecuteOperationAsync(LoadModels);
        }

        #region Private methods

        private void ModelsView_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                ModelViewModel mvm = (ModelViewModel)e.NewItems[0];

                // Remove from the candidates
                this.Candidates.Remove(mvm);

                // Autoselect promoted model
                this.ModelsView.MoveCurrentTo(mvm);

                // Reset current model
                this.CurrentModel = null;
            }
        }

        private void LoadModels(AsyncOperation operation)
        {
            // TEMP
            operation.Post(s => this.Models.AddRange(Enumerable.Range(1, 10).Select(n => new ModelViewModel
            {
                FullName = "Modella " + n,
                Multimedia =
                {
                    new DesignMultimediaImage { UriSource = new Uri("pack://application:,,,/SampleData/Images/FakeModel (" + n + ").jpg")},
                }
            })), null);

            operation.Post(s => HandlePromotions(), null);
        }

        private bool CanRecordMovie()
        {
            return this.CurrentModel.IsNotNull();
        }

        private void RecordMovie()
        {
            if (!CanRecordMovie())
                throw new InvalidOperationException("Cannot record a new movie");

            using (RecordViewModel rvm = new RecordViewModel())
            {
                this.Messenger.Send(new ShowDialogMessage(rvm, r =>
                {
                    if (rvm.Multimedia != null)
                    {
                        this.CurrentModel.Multimedia.Add(rvm.Multimedia);
                        this.CurrentModel.MultimediaView.MoveCurrentTo(rvm.Multimedia);
                    }
                }));
            }
        }

        private void SelectStartupCandidateCallback(bool? result)
        {
            ModelViewModel selectedCandidate = newCandidatesViewModel.CandidatesView.CurrentItem as ModelViewModel;

            // Copy already loaded candidates on the Candidates list
            this.Candidates.Clear();
            this.Candidates.AddRange(newCandidatesViewModel.Candidates);

            // Select the prechoosen candidate
            if (selectedCandidate != null)
            {
                this.CandidatesView.MoveCurrentTo(selectedCandidate);
                this.CurrentModel = selectedCandidate;
                this.CurrentModel.MultimediaView.MoveCurrentToFirst();
            }

            newCandidatesViewModel = null;

            //OpenCurrentMultimedia();
        }

        private Predicate<object> GetFilterForModel(string value)
        {
            return m =>
            {
                ModelViewModel mvm = (ModelViewModel)m;
                return (mvm.FullName.IndexOf(value, StringComparison.CurrentCultureIgnoreCase) >= 0);
            };
        }

        private void Close()
        {

        }

        private bool CanOpenCurrentMultimedia()
        {
            return this.CurrentModel != null && this.CurrentModel.MultimediaView.CurrentItem != null;
        }

        private void OpenCurrentMultimedia()
        {
            if (!CanOpenCurrentMultimedia())
                throw new InvalidOperationException("Cannot open current multimedia");

            ViewModelBase viewModel;
            Multimedia m = (Multimedia)this.CurrentModel.MultimediaView.CurrentItem;

            // Create view model basing on Multimedia type
            if (m is MultimediaImage)
                viewModel = new ImageEditorViewModel((MultimediaImage)m);
            else if (m is MultimediaMovie)
                viewModel = new MoviePlayerViewModel();
            else
                throw new NotSupportedException("Unknown multimedia type");

            this.Messenger.Send(new ShowDialogMessage(viewModel));
        }

        private void HandlePromotions()
        {
            this.ModelsView.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ModelsView_CollectionChanged);
        }

        #endregion
    }

}